﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using Meraz.Core.Model;
using System.Web;
using System.Data.EntityClient;
using System.Data.Common;
using System.Data;

namespace Meraz.Core.Data
{
    public class MerazContext : ObjectContext, IMerazContext
    {
        private static String MAIN_CONTEXT_KEY = "MerazContext";
        private static MerazContext _context;
        public static IMerazContext Instance
        {
            get
            {
                if (HttpContext.Current == null)
                {
                    if (_context == null)
                    {
                        _context = new MerazContext();
                    }
                    return _context;
                }
                if (!HttpContext.Current.Items.Contains(MAIN_CONTEXT_KEY))
                    HttpContext.Current.Items.Add(MAIN_CONTEXT_KEY, new MerazContext());
                return HttpContext.Current.Items[MAIN_CONTEXT_KEY] as MerazContext;
            }
        }


        private ObjectSet<Alias> _aliases;
        private ObjectSet<Blog> _blogs;
        private ObjectSet<BlogStudy> _blogStudies;
        private ObjectSet<Domain> _domains;
        private ObjectSet<Frame> _frames;
        private ObjectSet<Link> _links;
        private ObjectSet<Member> _members;
        private ObjectSet<MemberRole> _memberRoles;
        private ObjectSet<Role> _roles;
        private ObjectSet<Person> _people;
        private ObjectSet<Post> _posts;
        private ObjectSet<Poster> _posters;
        private ObjectSet<Topic> _topics;
        private ObjectSet<Tweet> _tweets;
        private ObjectSet<TwitterClient> _twitterClients;
        private ObjectSet<TwitterLink> _twitterLinks;
        private ObjectSet<TwitterMention> _twitterMentions;
        private ObjectSet<TwitterStudy> _twitterStudies;
        private ObjectSet<TwitterTag> _twitterTags;
        private ObjectSet<TwitterUser> _twitterUsers;
        private ObjectSet<Issue> _issues;
        private ObjectSet<Url> _urls;
        private ObjectSet<UrlRedirect> _urlRedirects;
        public MerazContext()
            : base("name=MerazEntities", "MerazEntities")
        {
            ContextOptions.LazyLoadingEnabled = true;
            _aliases = CreateObjectSet<Alias>();
            _blogs = CreateObjectSet<Blog>();
            _blogStudies = CreateObjectSet<BlogStudy>();
            _domains = CreateObjectSet<Domain>();
            _frames = CreateObjectSet<Frame>();
            _links = CreateObjectSet<Link>();
            _memberRoles = CreateObjectSet<MemberRole>();
            _members = CreateObjectSet<Member>();
            _roles = CreateObjectSet<Role>();
            _people = CreateObjectSet<Person>();
            _posts = CreateObjectSet<Post>();
            _posters = CreateObjectSet<Poster>();
            _topics = CreateObjectSet<Topic>();
            _tweets = CreateObjectSet<Tweet>();
            _twitterClients = CreateObjectSet<TwitterClient>();
            _twitterLinks = CreateObjectSet<TwitterLink>();
            _twitterMentions = CreateObjectSet<TwitterMention>();
            _twitterStudies = CreateObjectSet<TwitterStudy>();
            _twitterTags = CreateObjectSet<TwitterTag>();
            _twitterUsers = CreateObjectSet<TwitterUser>();
            _issues = CreateObjectSet<Issue>();
            _urls = CreateObjectSet<Url>();
            _urlRedirects = CreateObjectSet<UrlRedirect>();
        }

        public IObjectSet<Alias> Aliases { get { return _aliases; } }
        public IObjectSet<Blog> Blogs { get { return _blogs; } }
        public IObjectSet<BlogStudy> BlogStudies { get { return _blogStudies; } }
        public IObjectSet<Domain> Domains { get { return _domains; } }
        public IObjectSet<Frame> Frames { get { return _frames; } }
        public IObjectSet<Link> Links { get { return _links; } }
        public IObjectSet<Member> Members { get { return _members; } }
        public IObjectSet<MemberRole> MemberRoles { get { return _memberRoles; } }
        public IObjectSet<Role> Roles { get { return _roles; } }
        public IObjectSet<Person> People { get { return _people; } }
        public IObjectSet<Post> Posts { get { return _posts; } }
        public IObjectSet<Poster> Posters { get { return _posters; } }
        public IObjectSet<Topic> Topics { get { return _topics; } }
        public IObjectSet<Tweet> Tweets { get { return _tweets; } }
        public IObjectSet<TwitterClient> TwitterClients { get { return _twitterClients; } }
        public IObjectSet<TwitterLink> TwitterLinks { get { return _twitterLinks; } }
        public IObjectSet<TwitterMention> TwitterMentions { get { return _twitterMentions; } }
        public IObjectSet<TwitterStudy> TwitterStudies { get { return _twitterStudies; } }
        public IObjectSet<TwitterTag> TwitterTags { get { return _twitterTags; } }
        public IObjectSet<TwitterUser> TwitterUsers { get { return _twitterUsers; } }
        public IObjectSet<Issue> Issues { get { return _issues; } }
        public IObjectSet<Url> Urls { get { return _urls; } }
        public IObjectSet<UrlRedirect> UrlRedirects { get { return _urlRedirects; } }


        public void AddToAliases(Alias entity) { Aliases.AddObject(entity); }
        public void AddToBlogs(Blog entity) { Blogs.AddObject(entity); }
        public void AddToBlogStudies(BlogStudy entity) { BlogStudies.AddObject(entity); }
        public void AddToDomains(Domain entity) { Domains.AddObject(entity); }
        public void AddToFrames(Frame entity) { Frames.AddObject(entity); }
        public void AddToIssues(Issue entity) { Issues.AddObject(entity); }
        public void AddToLinks(Link entity) { Links.AddObject(entity); }
        public void AddToMembers(Member entity) { Members.AddObject(entity); }
        public void AddToMemberRoles(MemberRole entity) { MemberRoles.AddObject(entity); }
        public void AddToRoles(Role entity) { Roles.AddObject(entity); }
        public void AddToPeople(Person entity) { People.AddObject(entity); }
        public void AddToPosts(Post entity) { Posts.AddObject(entity); }
        public void AddToPosters(Poster entity) { Posters.AddObject(entity); }
        public void AddToTopics(Topic entity) { Topics.AddObject(entity); }
        public void AddToTweets(Tweet entity) { Tweets.AddObject(entity); }
        public void AddToTwitterClients(TwitterClient entity) { TwitterClients.AddObject(entity); }
        public void AddToTwitterLinks(TwitterLink entity) { TwitterLinks.AddObject(entity); }
        public void AddToTwitterMentions(TwitterMention entity) { TwitterMentions.AddObject(entity); }
        public void AddToTwitterStudies(TwitterStudy entity) { TwitterStudies.AddObject(entity); }
        public void AddToTwitterTags(TwitterTag entity) { TwitterTags.AddObject(entity); }
        public void AddToTwitterUsers(TwitterUser entity) { TwitterUsers.AddObject(entity); }
        public void AddToUrls(Url entity) { Urls.AddObject(entity); }
        public void AddToUrlRedirects(UrlRedirect entity) { UrlRedirects.AddObject(entity); }

        public void LoadAggregate(Post post)
        {
            LoadProperty<Post>(post, load => load.Body);
        }

        public void DeleteTweet(long tweetID)
        {
            EntityConnection entityConnection = (EntityConnection)Connection;
            DbConnection storeConnection = entityConnection.StoreConnection;

            storeConnection.Open();
            using (DbCommand command = storeConnection.CreateCommand())
            {
                command.CommandText = "DeleteTweet";
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("tweetID", tweetID));
                command.ExecuteNonQuery();
                command.Connection.Close();
            }
        }

        public void CreateTwitterLink(long tweetID, int urlID, int sequence, string originalUrl, string tone, bool isError)
        {
            EntityConnection entityConnection = (EntityConnection)Connection;
            DbConnection storeConnection = entityConnection.StoreConnection;

            storeConnection.Open();
            using (DbCommand command = storeConnection.CreateCommand())
            {
                command.CommandText = "CreateTwitterLink";
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("pTweetID", tweetID));
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("pUrlID", urlID));
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("pSequence", sequence));
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("pOriginal", originalUrl));
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("pTone", tone));
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("pIsError", isError));
                command.ExecuteNonQuery();
                command.Connection.Close();
            }
        }

        public int CreateUrlRedirect(string startUrl, string finishUrl)
        {
            EntityConnection entityConnection = (EntityConnection)Connection;
            DbConnection storeConnection = entityConnection.StoreConnection;
            int result;
            storeConnection.Open();
            using (DbCommand command = storeConnection.CreateCommand())
            {
                command.CommandText = "CreateUrlRedirect";
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("startUrl", startUrl));
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("finishUrl", finishUrl));
                object scalar = command.ExecuteScalar();
                if (!Int32.TryParse(scalar.ToString(), out result))
                    result = 0;
                command.Connection.Close();
            }
            return result;
        }

        public int CreateDomain(string domainName, int parent)
        {
            EntityConnection entityConnection = (EntityConnection)Connection;
            DbConnection storeConnection = entityConnection.StoreConnection;
            int result;
            storeConnection.Open();
            using (DbCommand command = storeConnection.CreateCommand())
            {
                command.CommandText = "CreateDomain";
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("domainName", domainName));
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("parent", parent));
                if (!Int32.TryParse(command.ExecuteScalar().ToString(), out result))
                    result = 0;
                command.Connection.Close();
            }
            return result;
        }

        public int CreateUrl(string url, int domainID)
        {
            EntityConnection entityConnection = (EntityConnection)Connection;
            DbConnection storeConnection = entityConnection.StoreConnection;
            int result;
            storeConnection.Open();
            using (DbCommand command = storeConnection.CreateCommand())
            {
                command.CommandText = "CreateUrl";
                command.CommandType = CommandType.StoredProcedure;
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("urlName", url));
                command.Parameters.Add(new MySql.Data.MySqlClient.MySqlParameter("domID", domainID));
                if (!Int32.TryParse(command.ExecuteScalar().ToString(), out result))
                    result = 0;
                command.Connection.Close();
            }
            return result;
        }
        public void Save()
        {
            this.SaveChanges();
        }
        public void SaveAndAccept()
        {
            this.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
        }
    }
}
